// wrapped by build app
define("dojox/wire/TreeAdapter", ["dijit", "dojo", "dojox", "dojo/require!dojox/wire/CompositeWire"], function (dijit, dojo, dojox) {
    dojo.provide("dojox.wire.TreeAdapter");

    dojo.require("dojox.wire.CompositeWire");

    dojo.declare("dojox.wire.TreeAdapter", dojox.wire.CompositeWire, {
        // summary:
        //		A composite Wire for tree nodes
        // description:
        //		This class has multiple child Wires for tree nodes, their title and
        //		child nodes.
        //		The root object for this class must be an array.
        //		'node' Wires in 'nodes' property is used to identify an object
        //		representing a node.
        //		'title' Wires in 'nodes' property is used to get the title string
        //		of a node.
        //		'children' Wires in 'nodes' property is used to iterate over child
        //		node objects.
        //		The node values are returned in an array as follows:
        // |		[
        // |			{title: title1,
        // |	  	 	children: [
        // |				{title: title2,
        // |				 child: ...},
        // |				{title: title3,
        // |				 child: ...},
        // |				...
        // |			]},
        // |			...
        // |		]
        //		This class only supports getValue(), but not setValue().

        _wireClass:"dojox.wire.TreeAdapter",

        constructor:function (/*Object*/ args) {
            // summary:
            //		Initialize properties
            // description:
            //		If object properties ('node', 'title' and 'children') of array
            //		elements specified in 'nodes' property are not Wires, Wires are
            //		created from them as arguments, with 'parent' property set to
            //		this Wire instance.
            // args:
            //		Arguments to initialize properties:
            //
            //		- nodes: An array containing objects for child Wires for node values
            this._initializeChildren(this.nodes);
        },
        _getValue:function (/*Array*/object) {
            // summary:
            //		Return an array of tree node values
            // description:
            //		This method iterates over an array specified to 'object'
            //		argument and calls getValue() method of 'node' Wires with each
            //		element of the array to get object(s) that represents nodes.
            //		(If 'node' Wires are omitted, the array element is used for
            //		further processing.)
            //		Then, getValue() method of 'title' Wires are called to get
            //		title strings for nodes.
            //		(If 'title' Wires are omitted, the objects representing nodes
            //		are used as title strings.)
            //		And if an array of objects with 'node' and 'title' Wires is
            //		specified to 'children', it is used to gather child nodes and
            //		their title strings in the same way recursively.
            //		Finally, an array of the top-level node objects are retuned.
            // object:
            //		A root array
            // returns:
            //		An array of tree node values
            if (!object || !this.nodes) {
                return object; //Array
            }

            var array = object;
            if (!dojo.isArray(array)) {
                array = [array];
            }

            var nodes = [];
            for (var i in array) {
                for (var i2 in this.nodes) {
                    nodes = nodes.concat(this._getNodes(array[i], this.nodes[i2]));
                }
            }
            return nodes; //Array
        },

        _setValue:function (/*Array*/object, /*Array*/value) {
            // summary:
            //		Not supported
            throw new Error("Unsupported API: " + this._wireClass + "._setValue");
        },

        _initializeChildren:function (/*Array*/children) {
            // summary:
            //		Initialize child Wires
            // description:
            //		If 'node' or 'title' properties of array elements specified in
            //		'children' argument are not Wires, Wires are created from them
            //		as arguments, with 'parent' property set to this Wire instance.
            //		If an array element has 'children' property, this method is
            //		called recursively with it.
            // children:
            //		An array of objects containing child Wires
            if (!children) {
                return; //undefined
            }

            for (var i in children) {
                var child = children[i];
                if (child.node) {
                    child.node.parent = this;
                    if (!dojox.wire.isWire(child.node)) {
                        child.node = dojox.wire.create(child.node);
                    }
                }
                if (child.title) {
                    child.title.parent = this;
                    if (!dojox.wire.isWire(child.title)) {
                        child.title = dojox.wire.create(child.title);
                    }
                }
                if (child.children) {
                    this._initializeChildren(child.children);
                }
            }
        },

        _getNodes:function (/*Object*/object, /*Object*/child) {
            // summary:
            //		Return an array of tree node values
            // description:
            //		This method calls getValue() method of 'node' Wires with
            //		'object' argument to get object(s) that represents nodes.
            //		(If 'node' Wires are omitted, 'object' is used for further
            //		processing.)
            //		Then, getValue() method of 'title' Wires are called to get
            //		title strings for nodes.
            //		(If 'title' Wires are omitted, the objects representing nodes
            //		are used as title strings.)
            //		And if an array of objects with 'node' and 'title' Wires is
            //		specified to 'children', it is used to gather child nodes and
            //		their title strings in the same way recursively.
            //		Finally, an array of node objects are returned.
            // object:
            //		An object
            // child:
            //		An object with child Wires
            // returns:
            var array = null;
            if (child.node) {
                array = child.node.getValue(object);
                if (!array) {
                    return [];
                }
                if (!dojo.isArray(array)) {
                    array = [array];
                }
            } else {
                array = [object];
            }

            var nodes = [];
            for (var i in array) {
                object = array[i];
                var node = {};
                if (child.title) {
                    node.title = child.title.getValue(object);
                } else {
                    node.title = object;
                }
                if (child.children) {
                    var children = [];
                    for (var i2 in child.children) {
                        children = children.concat(this._getNodes(object, child.children[i2]));
                    }
                    if (children.length > 0) {
                        node.children = children;
                    }
                }
                nodes.push(node);
            }
            return nodes; //Array
        }
    });

});
